﻿using System.Data.Entity;
using System.Linq;
using Easy.Common;
using System.Data.Entity.Infrastructure;

namespace Easy.Domain.Core
{
    public class UnitOfWork : DbContext, IUnitOfWork
    {
        public UnitOfWork(string nameOrConnectionString)
            : base(nameOrConnectionString)
        {
            ((System.Data.Entity.Infrastructure.IObjectContextAdapter)this).ObjectContext.CommandTimeout = 180;
        }


        //TODO:
        public override int SaveChanges()
        {
            int effectNum = 0;

            try
            {
                //如果自动跟踪已关闭，保存前须手动跟踪一次
                if (!base.Configuration.AutoDetectChangesEnabled)
                {
                    base.ChangeTracker.DetectChanges();
                }

                effectNum = base.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                //TODO:

                throw ex;
            }

            return effectNum;
        }

        public void Commit()
        {
            this.SaveChanges();
        }

        public void RollbackStateChanges()
        {
            base.ChangeTracker.Entries()
                .ToList()
                .ForEach(e => e.State = EntityState.Unchanged);
        }

        public void Clear()
        {
            base.ChangeTracker.Entries()
                .ToList()
                .ForEach(e => e.State = EntityState.Detached);
        }

        public void Attach<T>(T item) where T : class
        {
            CheckHelper.NotNull(item, "item");

            base.Entry(item).State = EntityState.Unchanged;
        }

        public void Detach<T>(T item) where T : class
        {
            CheckHelper.NotNull(item, "item");

            base.Entry(item).State = EntityState.Detached;
        }

        public void SetModified<T>(T item) where T : class
        {
            CheckHelper.NotNull(item, "item");

            base.Entry(item).State = EntityState.Modified;
        }

        public void ApplyCurrentValues<T>(T toOriginal, T formCurrent) where T : class
        {
            base.Entry<T>(toOriginal).CurrentValues.SetValues(formCurrent);
        }

        public string ConnectionString
        {
            get { return this.Database.Connection.ConnectionString; }
        }
    }
}
